package org.rqb.service;

import lombok.extern.slf4j.Slf4j;
import org.rqb.entry.Point;
import org.rqb.utils.ProxyConversionUtil;
import org.yaml.snakeyaml.Yaml;

import javax.swing.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static org.rqb.utils.CodeUtil.base64Decode;
import static org.rqb.utils.ProxyConversionUtil.*;

@Slf4j
public class PointService {

    /**
     * 加载yaml文件转化为v2ray可以直接复制的base64为字符串
     * @param path
     * @param callback
     */
    public void ymlTransToV2rayNBase64(String path, Consumer<String> callback) {
        SwingWorker<String, Void> worker = new SwingWorker(){
            @Override
            protected String doInBackground() throws Exception {
                List<String> points = readYml(path);
                return urlListToBase64(points);
            }

            @Override
            protected void done() {
                try {
                    String result = (String) get(); // 获取 doInBackground 的返回值
                    callback.accept(result); // 通过回调传递结果
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        worker.execute();
    }

    /**
     *
     * @param base64Str
     * @param saveFilePath
     * @param callback
     */
    public void v2rayNBase64ToYml(String base64Str,String saveFilePath, Consumer<String> callback) {
        // 解码base64位
        String pointStr = base64Decode(base64Str); //节点字符串

        // 分割成单独的节点信息
        String[] points = pointStr.split("\n");

        //todo 分流节点解码
        List<Point> pointList = arrangePoint(points);

        //todo 封装

    }

    private List<Point> arrangePoint(String[] points) {
        ArrayList<Point> pointList = new ArrayList<>();
        if (points == null || points.length == 0) { //安全考虑，过滤空数组
            return pointList;
        }
        //遍历处理
        for (int i = 0; i < points.length; i++) {
            String pointStr = points[i];
            String type = pointStr.split("://")[0];

            switch (type.trim().toLowerCase()) {
                case "ss":
                case "shadowsocks":
                    pointList.add(ProxyConversionUtil.ssToYmlStr(pointStr));
                    break;
                case "vmess":
                    pointList.add(ProxyConversionUtil.vmessToYmlStr(pointStr));
                    break;
                case "vless":
                    pointList.add(ProxyConversionUtil.vlessToYmlStr(pointStr));
                    break;
                case "trojan":
                    pointList.add(ProxyConversionUtil.trojanToYmlStr(pointStr));
                    break;
            }



        }

        //返回过滤后的数据
        return pointList.stream().filter(Objects::nonNull).collect(Collectors.toList());
    }


    /**
     * 将多个 订阅链接转换为 Base64 格式
     */
    private String urlListToBase64(List<String> urlList) {
        String joinedUrls = String.join("\n", urlList); // 以换行符连接多个 SS 链接
        return Base64.getEncoder().encodeToString(joinedUrls.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 返回节点集合
     * @param filePath
     * @return
     */
    private  List<String> readYml(String filePath) {
        ArrayList<String> points = new ArrayList<>();
        Yaml yaml = new Yaml();

        try (FileInputStream inputStream = new FileInputStream(filePath)) {
            // 解析 YAML
            Map<String, Object> data = yaml.load(inputStream);
            List<Map<String, Object>> proxies = (List<Map<String, Object>>) data.get("proxies");

            // 解析为 Point 对象
            for (Map<String, Object> proxy : proxies) {
                String name = (String) proxy.get("name");
                String server = (String) proxy.get("server");
                int port = (Integer) proxy.get("port");
                String type = (String) proxy.get("type");
                String cipher = (String) proxy.get("cipher");
                String password = (String) proxy.get("password");
                String plugin = (String) proxy.get("plugin");
                Boolean udp = (Boolean) proxy.get("udp");
                LinkedHashMap pluginOptsLinkHashMap;
                String mode = null;
                String host = null;
                if ((pluginOptsLinkHashMap = (LinkedHashMap) proxy.get("plugin-opts")) != null){
                    mode = (String) pluginOptsLinkHashMap.get("mode");
                    host = (String) pluginOptsLinkHashMap.get("host");

                }
                String uuid = (String) proxy.get("uuid");
                Integer alterId = (Integer) proxy.get("alterId");
                Boolean tls = (Boolean) proxy.get("tls");
                Boolean skipCertVerify = (Boolean) proxy.get("skip-cert-verify");
                String network = (String) proxy.get("network");
                LinkedHashMap wsOpts = (LinkedHashMap) proxy.get("ws-opts");
                String path = null;
                if (wsOpts != null){
                    path = (String) wsOpts.get("path");
                    host = (String) ((LinkedHashMap) wsOpts.get("headers")).get("Host");
                }
                String sni = (String) proxy.get("sni");


                //封装参数
                Point point = new Point(name,server,port,type,cipher,password,plugin,udp,mode,host,uuid,alterId,tls,skipCertVerify,network,path,sni);


                //分别处理
                if (type == null || type.isEmpty()) {
                    log.info("协议类型为空,节点信息如下： " + point.toString());
                    continue;
                }
                switch (type.trim().toLowerCase()) {
                    case "ss":
                    case "shadowsocks":
                        points.add(ssToV2Str(point));
                        break;
                    case "vmess":
                        points.add(vmessToV2Str(point));
                        break;
                    case "vless":
                        points.add(vlessToV2Str(point));
                        break;
                    case "trojan":
                        points.add(trojanToV2Str(point));
                        break;
                }


            }

        } catch (FileNotFoundException e) {
            log.error("读取 YAML 文件异常: 文件未找到");
        } catch (IOException e) {
            log.error("读取 YAML 文件异常", e);
        }

        return points;
    }




}

